As is known in the art, various devices or programs (herein collectively referred to as an interrupt source or sources) generate interrupts to notify a CPU of various events, such as the requirement to service an interrupt. An interrupt may be described as a signal from the interrupt source that causes the CPU to stop current processing and handle, i.e., service, the interrupt. One technique used to signal interrupt events to the CPU is through Message Signal Interrupt (MSI)/MSI-X based interrupts. Here, the interrupt source sends the interrupt message with an associated interrupt ID.
More particularly, there may be many interrupt classes or types in the system. Each interrupt class is represented by one MSI_X interrupt ID. Fatal interrupt, non-fatal interrupt, “data-movement-done” interrupt are few examples of interrupt classes. Each interrupt class (say fatal interrupt) may be generated by one, or more interrupt sources. Each interrupt source corresponds to a bit in the interrupt holding register. Thus, for a system having a plurality of N classes of interrupts and M potential interrupt sources there would be N interrupt holding registers, each holding the interrupts for a corresponding one of the N interrupt classes and each bit in each one of the N holding registers corresponding to one of the M interrupt sources.
As is also known in the art, Message Signaled Interrupts (MSI_X) is a feature in computing systems that enables devices in the system to request service from the system CPU by writing messages to location addresses based on the class of service requested. MSI_X is a posted write operation that shares the same queue as a normal posted writes from IO device to the CPU controller, namely “posted write queue”. For various reasons (e.g, high performance IO devices), read responses to the CPU could have a separate queue namely “read response queue”. Both these queues are arbitrated for, by the, “merge queue arbiter” before being placed in the “merge queue” destined to the CPU. In such an environment, potential ordering/coherency issues could arise when read responses could get ahead of posted write requests including MSI_X writes. When an interrupt event occurs, the corresponding bit(s) in the interrupt holding register would be asserted and that would trigger the logic to schedule an MSI_X posted write into the “posted write queue”. When software reads the interrupt holding register, the potential of reordering interrupt holding register read response ahead of the posted MSI_X interrupt message write request could result in a ghost interrupt flagged to the processor due to this reordering.
More particularly, and referring to FIG. 1, a system is shown that supports MSI_X messaging to service interrupts from a plurality of different interrupt sources. Interrupt detection logic is provided to detect and direct the interrupt sources into various interrupt holding registers to facilitate hardware and software interrupt management. From the system perspective, each interrupt source/event has to be uniquely identified (i.e., assigned a unique name, or a unique ID). In the MSI_X case, each interrupt source/event is given a unique interrupt ID. In FIG. 1, reg_0 has M+1 interrupt source bits and each of these bits would represent an interrupt source/event that is uniquely identified by an MSI_X interrupt ID.
In FIG. 1, the data in the N holding registers are fed to an MSI_X generate logic. The MSI_X generate logic schedules (i.e., post) these interrupts to a write queue. For example, if three inputs to the MSI_X generate logic are set; i.e., here a logic 1, at the same time, say one from reg_0, another from reg_1 and a third from reg_2, the MSI_X generate logic would post reg_0 interrupt to the write queue, followed by reg_1 message, then reg_2 message, for example.
The output of the MSI_X generate logic along with write data to be processed by the CPU are fed to the posted write queue (e.g., a FIFO). Note that the posted write queue holds interrupts as well as normal data traffic. Read response queue holds the read response for reads by the CPU from the interrupt holding registers. Both of these queues have to arbitrate to get access to the merge queue. A merge queue arbiter provides arbitration between the posted write queue and the read response queue for access to the CPU.
In FIG. 1, It should be noted that the reading by the CPU of the interrupt holding registers is asynchronous with the interrupt vectors being posted through the write queue to the CPU. It is also noted that with this arrangement, the write queue may receive an interrupt that, for example, ID 200, indicating holding reg_1, has an interrupt that needs servicing. However, because of the arbitration, that interrupt may get “stuck” in the write queue (i.e., may not passbe read from the write queue for servicing by the CPU until after the CPU has read the read queue). Thus, because of the asynchronous operation of the CPU in reading the read queue with respect to the write queue, the CPU may receive the information from the read queue for, in this example, reg_1 before the interrupt for that register passes from the write queue to the CPU. Thus, if the CPU services the interrupt event based on the data it received from the read queue and then gets the interrupt from the write queue, the CPU may think, incorrectly, that reg_1 still has an interrupt to service when in fact the CPU has all ready served that interrupt. Thus, in such an environment, potential ordering/coherency issues could arise when read responses could get ahead of posted write requests including MSI_X writes.
As is also known in the art, one type of bus used for communicating with peripheral or Input/Output (IO) devices, such as hard disks, is a Peripheral Component Interconnect (PCI) bus. According to PCI specifications, an IO device that supports MSI_X functionality requires 16 bytes of information per MSI_X interrupt vector. This information is normally stored in an IO device memory array and used during the generation of an MSI_X message.
More particularly, and referring again to FIG. 1, as noted above, interrupt sources (e.g., an IO) are grouped into “N” interrupt holding registers, each interrupt holding register having “M+1” bits. Each interrupt source is directly connected to the MSI_X generation logic which is then mapped into a unique MSI_X vector. This approach would require the IO device to support (M+1)*N MSI_X vectors. Such, however, increases the memory requirement for an IO device that supports a large number of interrupt sources; burdens the MSI_X generation logic in an IO device when handling and scheduling large number of simultaneous interrupt events; burdens the system interrupt controller (i.e., the processor) by having it to support a large number of MSI_X vectors; and increases the system traffic of MSI_X message writes to the system controller, since each interrupt event would result in an MSI_X message write.